﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;

namespace FileManagerSystem.Models
{
    /// <summary>
    /// 分片上传文件前台传送的具体信息
    /// </summary>
    public class ChunkFileUploadDetail
    {
        /// <summary>
        /// 文件名
        /// </summary>
        public string name { get; set; }
        /// <summary>
        /// 会话标识
        /// <para>第一片文件上传时不需提供此参数，置位空就行，但是从第二片开始需要携带guid</para>
        /// <para>后台会在第一片文件上传成功后给前端返回session，起到标识会话的作用</para>
        /// </summary>
        public string session { get; set; }
        /// <summary>
        /// 前端解析的文件md5
        /// <para>仅需解析第一个分片即可</para>
        /// </summary>
        public string md5 { get; set; }
        /// <summary>
        /// 分片大小
        /// <para>最长不允许超过长整形的 9223372036854775807 字节</para>
        /// </summary>
        public long chunkSize { get; set; }
        /// <summary>
        /// 文件总大小
        /// <para>最长不允许超过长整形的 9223372036854775807 字节</para>
        /// </summary>
        public long fileSize { get; set; }
        /// <summary>
        /// 第几个区块
        /// <para>（范围从1到2147483647）</para>
        /// <para>（如果chunk=maxChunk=1，则认为是单文件直接上传）</para>
        /// </summary>
        [Range(1, int.MaxValue, ErrorMessage = "当前区块数必须是大于0的自然数！")]
        public int chunk { get; set; }
        /// <summary>
        /// 总共多少区块
        /// <para>（范围从1到2147483647）</para>
        /// <para>（如果chunk=maxChunk=1，则认为是单文件直接上传）</para>
        /// </summary>
        [Range(1, int.MaxValue, ErrorMessage = "总区块数必须是大于0的自然数！")]
        public int maxChunk { get; set; }
        /// <summary>
        /// 上传状态
        /// <para>0-第一片上传 1-正常继续上传 2-断点续传 3-最后一片上传 </para>
        /// </summary>
        [Range(0, 3, ErrorMessage = "上传状态仅允许是0到3的整形数字！")]
        public int statu { get; set; }
        /// <summary>
        /// 文件所属的虚拟顶级目录Guid（可选）
        /// <para>（可以为空，为空是表示是单文件上传，没有所属文件夹）</para>
        /// <para>以后多文件打包下载时，会依此重建文件夹</para>
        /// <para>本虚拟路径依赖于前端 "文件夹上传" 时提供</para>
        /// <para>！！！多个文件存在于同一个文件夹时，请务必确保此GUID一致！！！</para>
        /// </summary>
        public string topDirGuid { get; set; }
        /// <summary>
        /// 文件所在虚拟子目录
        /// <para>（可以为空，为空标识没有上级目录）</para>
        /// <para>以后多文件打包下载时候会根据这个虚拟目录，并基于虚拟顶级目录重建文件夹</para>
        /// <para>本虚拟路径依赖于前端 "文件夹上传" 时提供</para>
        /// </summary>
        public string path { get; set; }
        /// <summary>
        /// 文件分片
        /// </summary>
        public IFormFile file { get; set; }
    }

    /// <summary>
    /// 上传状态枚举
    /// </summary>
    public enum UploadStatu
    {
        /// <summary>
        /// 初始化上传，前端初次上传时状态，后台看到此状态主要会校验md5，检测是否秒传或者缺分片
        /// </summary>
        Init = 0,
        /// <summary>
        /// 常规上传，前端给此状态，上传时均用此状态
        /// </summary>
        Uploading = 1,
        /// <summary>
        /// 断点续传，后台给此状态，前端根据这个状态去上传遗漏的分片
        /// </summary>
        ResumeUploading = 2,
        /// <summary>
        /// 完成上传，前端给此状态，后台根据这个状态自动去合并文件；后台给此状态，前端根据这个状态弹窗提示已经完成上传
        /// </summary>
        Finish = 3,
        /// <summary>
        /// 秒传，后台给此状态，前端根据这个状态去跳过当前文件上传
        /// </summary>
        RapidUpload = 4
    }

    /// <summary>
    /// 每个分片上传后的返回信息
    /// </summary>
    public class FileUploadResult
    {
        public string Name { get; set; }
        /// <summary>
        /// 会话标识
        /// <para>后台会在第一片文件上传成功后给前端返回session标识，之后会一直需要前端携带session标识</para>
        /// </summary>
        public string Session { get; set; }
        /// <summary>
        /// 文件最终保存的guid
        /// <para>完整文件保存成功后，才会返回文件标识</para>
        /// </summary>
        public string FileGuid { get; set; }
        /// <summary>
        /// 文件md5（第一片文件）
        /// </summary>
        public string Md5 { get; set; }
        /// <summary>
        /// 刚刚上传成功的是第几片
        /// </summary>
        public int Chunk { get; set; }
        /// <summary>
        /// 上传状态 1-要求前端继续上传 2-要求前端断点续传 3-文件上传完毕 4-秒传成功
        /// </summary>
        [Range(1, 4, ErrorMessage = "返回的上传状态仅允许是1到4的整形数字！")]
        public int Statu { get; set; }
        /// <summary>
        /// 缺少的分片文件（如果是断点续传时，这里会给数据，否则这里是空的）
        /// </summary>
        public List<int> LackedChunks { get; set; } = new List<int>();
    }

    /// <summary>
    /// 新建虚拟目录
    /// </summary>
    public class DirectoryDetail
    {
        /// <summary>
        /// 文件夹名
        /// </summary>
        public string Name { get; set; }
    }
}
